//============================================================================
// Author      : Ting Lei, leiting@gmail.com
// Version     :
// Copyright   : all rights reserved, see LICENSE file
// Description : functions interfacing mincost.cpp to postgres
//============================================================================

#include <vector>
#include <set>
#include <map>
#include <float.h>

#include <iostream>
#include <fstream>
#include <sstream>

#include "my_func.h"
#include "mincost_ns.hpp"
//#include "prettyprint.hpp"

#include "nametable.hpp"

#include "mincost_ns.hpp"

extern "C" int mincost_ns_process(input_t * edge_tuples, int length, const vertex_name_c_t src, const vertex_name_c_t dst, int requiredFlow, output_t** p_output_tuples, int* result_length);
#include "my_func.h" //transfer C to C-plus

extern "C" {
#include <postgres.h>  //for elog or elog.h //calling elog() makes the cpp file unsuitable for c main??
};
/*****              Load table tuples into structures                *****/

template <class T>
std::string show(T x)
{
    std::ostringstream buffer;
    buffer << x;

    return buffer.str();
}


int mincost_ns_process(input_t * edge_tuples, int length, const vertex_name_c_t src, const vertex_name_c_t dst, int requiredFlow, output_t** p_output_tuples, int *result_length){
  std::string err;

  std::set<vertex_name_t> vertex_set;
  std::vector<edge_t> edges(length);
  for (int i = 0; i < length; i++) {
	  auto input_edge = edge_tuples[i];
	  edges[i] = std::make_tuple(input_edge.origin_c, input_edge.destination_c
			  , input_edge.capacity_c
			  , input_edge.lowerbound_c, input_edge.cost_c, input_edge.value_c, input_edge.vname_c);
	  vertex_set.emplace(input_edge.origin_c);
	  vertex_set.emplace(input_edge.destination_c);
  }
  std::vector<vertex_name_t> vertices(vertex_set.begin(),vertex_set.end());
  std::sort(vertices.begin(), vertices.end());
  nametable<vertex_name_t> vertex_nt;
  vertex_nt.from_vec(vertices);


  vertex_name_t s = src, t = dst;

  Weight totalCost = 0;
  int res = mincost_ns(edges, vertex_nt, s, t, requiredFlow, totalCost);
  bool feasible = (res == 0);
  if (!feasible) {
	  elog(NOTICE, "mincost_ns_process(): cannot find optimal solution");
  }

  //output
  const int numMetaVar = 3; //number of meta variables
  const int g_numEdges = (int) edges.size();
  *p_output_tuples = get_space_mincost(g_numEdges + numMetaVar);

  for(int i_rec = 0; i_rec <g_numEdges; i_rec ++){
	  auto& e = edges[i_rec];
	  set_tuple_mincost(i_rec, std::get<0>(e).c_str(), std::get<1>(e).c_str(), std::get<2>(e), std::get<3>(e), std::get<4>(e), std::get<5>(e), std::get<6>(e).c_str(), p_output_tuples);
  }

  set_tuple_mincost(g_numEdges    , "_meta", "_meta", 0, 0, 0, totalCost, "_meta_objective", p_output_tuples);
  set_tuple_mincost(g_numEdges + 1, "_meta", "_meta", 0, 0, 0, (feasible ? 1 : 0), "_meta_feasible", p_output_tuples);
  set_tuple_mincost(g_numEdges + 2, "_meta", "_meta", 0, 0, 0, 0, "_meta_unbounded", p_output_tuples);  

  elog(NOTICE, "mincost_ns_process(): returning %d edges", g_numEdges + numMetaVar);  //debug
  *result_length = g_numEdges + numMetaVar;
  return *result_length;
}
